home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gamers Delight 2
/
Gamers Delight 2.iso
/
Aminet
/
game
/
misc
/
CRobots.lha
/
CRobots
/
CRobots.doc
< prev
next >
Wrap
Text File
|
1990-04-16
|
61KB
|
1,622 lines
_____________________________________________________________
| |
|: :|
| ##### ###### ####### ###### ####### ####### ##### |
| # # # # # # # # # # # # # |
| # # # # # # # # # # # |
| # ###### # # ###### # # # ##### |
| # # # # # # # # # # # |
| # # # # # # # # # # # # # |
| ##### # # ####### ###### ####### # ##### |
|: :|
|_____________________________________________________________|
___ ____ ___
/ \ /\ /\ * / \ / \
/ \ / V \ _ | / \
| | | | | | | _ | |
|-----| | | | | | \ |-----|
| | | |V| | | | | | | |
| | |_| |_| |_| \_____/ | |
(C) Copyright 1985, Tom Poindexter
(C) Copyright 1989-90, David Wright - Amiga Version
David Wright
4262 Bennington
Brunswick, OH 44212
USA
(216) 273-1064
davewt@NCoast.ORG
uunet!hal!ncoast!davewt
uunet!cwjcc!ncoast!davewt (prefered)
Tom Poindexter '85 David Wright '89-90
_1_. _D_i_s_t_r_i_b_u_t_i_o_n _a_g_r_e_e_m_e_n_t_:
You may make copies of this program, manual, and other files and
give them to your friends, upload it to bulletin boards, or include
it in the library of a non-profit computer club. In short, you are
free to distribute at will with the exception of distribution for
profit.
_2_. _I_n_t_r_o_d_u_c_t_i_o_n
_2_-_1_. _D_e_s_c_r_i_p_t_i_o_n
CRobots ("see-robots") is a game based on computer programming.
Unlike arcade type games which require human input controlling some
object, all strategy in CRobots must be complete before the actual
game begins. Game strategy is condensed into a C language program
that you design and write. Your program controls a robot whose
mission is to seek out, track, and destroy other robots, each
running different programs. Each robot is equally equipped, and up
to four robots may compete at once. CRobots is best played among
several people, each refining their own robot program, then
matching program against program.
CRobots consists of a C compiler, a virtual computer, and
battlefield display. The CRobots compiler accecpts a limited (but
useful) subset of the C language. The robot programs are aided by
hardware functions to scan for opponents, start and stop drive
mechanisms, fire cannons, etc. After the programs are compiled and
loaded into separate robots, the battle is observed. Robots moving,
missiles flying and exploding, and certain status information are
displayed on the screen, in real-time.
_2_-_2_. _I_n_t_e_n_d_e_d _a_u_d_i_e_n_c_e
CRobots will most likely appeal to programmers (especially those
who think they can write the "best" programs), computer game
enthusiasts, people wishing to learn the C language, and those who
are interested in compiler design and virtual computer
interpreters.
_2_-_3_. _M_a_c_h_i_n_e _a_n_d _s_o_f_t_w_a_r_e _r_e_q_u_i_r_e_m_e_n_t_s
- Amiga 500, 1000, 2000, 2500
- 512k of RAM
- DOS 1.3 or higher
- ARP 1.3 or higher
- Monochrome or Color monitor
- Text editor (UE, TxEd, or your own favorite)
Page 1
Tom Poindexter '85 David Wright '89-90
NOTE FOR 512K 1000 & 500 USERS: I have tested version 2.3 on a
512k 1000, and was able to get it to work. If you have problems,
try setting the stack size to 25 or 30k. I was able to get it to
run by breaking out of the startup-sequence, setting the stack to
30k, and then running it. It might work with WB loaded, but with
only 512k it might be tight, and you might need to remove any
external drives.
_2_-_4_. _U_s_e_r _i_n_t_e_r_f_a_c_e
At the present time CRobots does not use menus, windows, pop-ups
(other than a file requester), or any other user-friendly
interface. Since the emphasis is on designing and writing robot
control programs, CRobots is usually started as a compiler is, from
the AmigaDOS command line, although a WorkBench interface is
available.
_3_. _T_y_p_e_s _o_f _p_l_a_y
CRobots can either run one match (single play), in which the
realtime battlefield simulator is used, or several matches (match
play), in which only the name of the winner is printed after each
match. Single play is the default. Match play is intended to see
how robot programs perform on the average. Match play can consume
several hours of computer time depending on the number of matches
and cpu cycle limit, and can be run overnight.
_4_. _R_u_n_n_i_n_g _C_R_o_b_o_t_s
_4_-_1_. _C_o_m_m_a_n_d _l_i_n_e _o_p_t_i_o_n_s
CRobots can be started from the CLI or a WorkBench icon. If it
is started from the CLI you may also specify several options.
Sample command line:
1>crobots [options] [robot-program-1 ... robot-program-n]
Valid options are:
TO file Save the output from the compile listing ("COMPILE"
option) or record matches ("MATCH" option) to <file>.
COMPILE Compile only, and produce virtual machine assembler
code and symbol tables. You must have the source code
(.r file) for a robot to use this function.
Page 2
Tom Poindexter '85 David Wright '89-90
DEBUG Compile one program, and invoke machine level
single step tracing. You must have the source code
(.r file) for a robot to use this function.
MATCH xxx Run a series of matches, where "xxx" is the number
of matches. If "MATCH" is NOT specified, then the
default is to run one match and display the
battlefield in realtime. If the MATCH option IS
selected, all the robots must be pre-compiled.
LIMIT xxx Limit the number of machine cpu cycles per match
when "MATCH" is specified. The default cycle limit
is 500,000.
NOSHOW Turn off compilation display to increase speed.
NOWAIT Turn off the "press any key" messages. Used mainly
when running a series of matches and output is
directed to a file with the TO option.
robot-programs The file name of the CRobots source program(s).
(Wildcards allowed) Up to four files may be
specified. If only one file is specified, it will
be "cloned" into another, so that two robots
(running the same program) will compete. Any file
name may be used, but for consistency please use
'.r' as an extension for source code. If you do
not give any robot file names, all the names you
give can't be found, or you run CRobots from the
WorkBench, the ARP file requester will come up
and allow you to select up to 4 robots.
If you do not wish to load 4 robots, just click
the CANCEL gadget after selecting the last robot
you want to load.
Note that some of these options are mutually-exclusive, and that
others will have no effect depending on the mode you are in.
_4_-_2_. _E_x_a_m_p_l_e_s_:
1) Watch three robots compete with full display:
1>crobots robot1.cr robot2.cr robot3.cr
2) Compile one robot, and save the listing:
1>crobots COMPILE TO robot1.lst robot1.r
3) Debug a robot (first get an assembler code listing,
as in example 2:
1>crobots DEBUG robot1.r
4) Run 50 matches, limiting total cpu cycles to 200,000
(per match), and save results:
Page 3
Tom Poindexter '85 David Wright '89-90
1>crobots MATCH 50 LIMIT 200000 TO save rbt1.cr rbt2.cr
5) Display command line options
1>crobots ?<return>?<return>
_4_-_3_. _R_u_n_n_i_n_g _C_R_o_b_o_t_s _f_r_o_m _t_h_e _W_o_r_k_B_e_n_c_h
If you wish you may start CRobots from the WorkBench by clicking
on it's icon. You may also specify some of the options that were
available from the CLI by using the icon's "tool types" array. You
can edit this array by clicking on the CRobots icon _o_n_c_e and then
selecting the menu option "Info". You will see a blank line that
has ADD and DEL gadgets to the right of it. Click the ADD gadget
and a cursor will appear at the start of the blank line. Type in
one of the following keywords followed by an equals sign, and the
value you want (value limits are the same as for the CLI options
above):
MATCHES
LIMIT
NOSHOW
Matches and limit take numeric arguments, as under the CLI,
while the noshow option should be followed by a YES if you wish to
turn the option on (see above for what the noshow flag does).
You may add as many of these options as you wish, but you must
use the ADD gadget to create each new option, and the DEL gadget to
delete options that you no longer want.
Once you have added/deleted the options that you want, click the
SAVE gadget to exit and save them to disk.
_4_-_4_. _W_o_r_k_b_e_n_c_h _e_x_a_m_p_l_e_s
1) Set the number of matches to 3, with a limit of
20,000 cycles per match:
MATCHES=3
LIMIT=20000
2) Turn off screen output of robot compilations:
NOSHOW=YES
_5_. _G_a_m_e _p_a_r_a_m_e_t_e_r_s
_5_-_1_. _B_a_t_t_l_e_f_i_e_l_d
The battlefield is a 1,000 by 1,000 meter square. A wall
surrounds the perimeter, so that a robot running into the wall will
incur damage. Note that as screen resolution is obviously less than
1000x1000, there is bound to be some error is scaling which will
make robots appear to be hit by pulses when they take no damage.
Page 4
Tom Poindexter '85 David Wright '89-90
Robots may also appear to go over each other, and take damage from
hitting walls when they appear to be a slight distance away from
them.
The lower left corner has the coordinates x = 0, y = 0; the
upper right corner has the coordinates x = 999, y = 999. There are
grids on the floor of the battlefield, and emitter/detector pairs
on the bottom of the robot which allow it to keep track of it's
position much like an optical mouse.
The compass system is oriented so that due east (right) is 0
degrees, 90 is north, 180 is west, 270 is south. One degree below
due east is 359.
135 90 45
\ | /
\ | /
180 --- x --- 0
/ | \
/ | \
225 270 315
_5_-_2_. _R_o_b_o_t _o_f_f_e_n_s_e
The main offensive weapons are the phased particle cannon (PPC)
and scanner. The PPC has a range of 700 meters. The PPC may be
fired an unlimited number of times, but a recharging factor
effectively limits the number of pulses in the air at any one time
to two. The PPC is mounted on an independent turret, and therefore
can fire any direction, 0-359, regardless of robot heading.
The scanner is an optical device that can instantly scan any
chosen heading, 0-359. The scanner has a maximum resolution of +/-
10 degrees. This enables the robot to quickly scan the field at a
low resolution, then use maximum resolution to pinpoint an
opponent.
_5_-_3_. _R_o_b_o_t _d_e_f_e_n_s_e
The only defenses available are the motor drive and status
registers. The motor can be engaged on any heading, 0-359, in
speeds from 0-100 percent of power. Robot mass is considerable, so
there are acceleration and deacceleration delay factors. A speed of
0 stops the motor. Turns can be negotiated at speeds of 50% and
less, in any direction. Of course, the motor drive can be engaged
any time, and is necessary on offense when a target is beyond the
700 meter range of the PPC.
There are several embedded controllers in the robot which
Page 5
Tom Poindexter '85 David Wright '89-90
utilize a shared memory system (18 DMA channels) to update certain
status registers without tying up the primary robot CPU. The
primary registers indicate the percent of damage, and current x and
y locations on the battlefield. Another register provides the
current drive speed.
_5_-_4_. _D_i_s_a_b_l_i_n_g _o_p_p_o_n_e_n_t_s
A robot is considered dead when the damage reaches 100%. Percent
of damage inflicted is as follows:
2% - collision into another robot (both robots in a
collision receive damage) or into a wall. A
collision also causes the motor drive to disengage,
and speed is reduced to 0.
3% - a pulse impacting within a 40 meter radius.
5% - a pulse impacting within a 20 meter radius.
10% - a pulse impacting within a 5 meter radius.
Damage is cumulative, and cannot be repaired. However, a robot
does not lose any mobility, firing potential, etc. at high damage
levels. In other words, a robot at 99% damage performs just as well
as a robot with no damage.
Page 6
Tom Poindexter '85 David Wright '89-90
_5_-_5_. _S_a_m_p_l_e _d_i_s_p_l_a_y
(Status
(x=999,y=999) blocks)
+------------------------------------+ 1 fubar.r
| | D% 015 Sc 218
| \|/ 1 | Sp 000 Hd 090
| (pulse impacting) -#- | ------------------
| /|\ | 2 snafu.r
(y | | D% 050 Sc 275
| + -------(particle | Sp 100 Hd 180
a | + --pulses) | ------------------
x | 2 | 3 bimbo.r
i | | D% 000 Sc 045
s) | 3 | Sp 000 Hd 000
| / | ------------------
| (robots) ----\ | 4 kumquat.r
| 4 | D% 100 Sc 050
| | Sp 000 Hd 335
| |
| |
+------------------------------------+ CPU Cycle: 4500
(x=0,y=0) (x axis)
The CRobots battle console consists of several color CRT's and
an LCD counter. The largest CRT is the primary battle display, and
displays the battle in real-time. The smaller CRT's are status
blocks for each robot.
Each status block shows the file name of the robot, the damage
incurred (D%), the current scan degrees (Sc), the speed (Sp), and
heading (Hd). Robots are represented on the field by a graphic
item, which is also displayed to the left of the name in the status
block for reference. If Damage is below 90%, it will be displayed
in green. If damage is between 90 & 100% it will be displayed in
red. When damage reaches 100%, it will be displayed in black.
The number of elapsed robot cpu cycles is shown in an LCD
display below the status blocks.
The CRobots program can be aborted at any time by pressing the
ESC key. It may also be paused at almost any time by pressing SPACE
or CTRL-S, and restarted by pressing SPACE again or CTRL-Q.
Page 7
Tom Poindexter '85 David Wright '89-90
_5_-_6_. _T_a_b_l_e _o_f _T_i_m_e _C_o_s_t_s
As just a few CPU cycles can make the difference between a
winner and loser, following is a table of the cost in CPU cycles of
various actions:
Action Cpu Cycles
----------------------------------
Recharge PPC 150
Acc/Decellerate 10% 10
Pulse traveling 50
meters 10
Robot move 7 meters
at 100% speed 1
_6_. _C_R_o_b_o_t_s _C_P_U
The robot cpu is a simple stack-oriented computer. It operates
at very slow speeds (on a 7.8 MHz 68000 Amiga with an average
amount of background tasks running and with two robots loaded, the
average speed is 309 instructions per second, .000309 mips!!). The
word size is 32 bits, allowing integer values from -2,147,483,648
to 2,147,483,647. There are internal pointer registers that manage
stack usage, but are not accessible from a robot program. The same
is true for an implicit accumulator.
The maximum code space is 1,000 instructions. All instructions
are equal in length. The maximum stack size is 500 words, which is
used for data and function call/returns. The stack grows upward for
data usage, and downward (from the end) for function call/returns.
Three words are used for each function call, and are released upon
the function return. The data portion and call/return portion are
managed by separate internal stack pointers.
If the data stack pointer and call/return stack pointer collide,
a stack overflow occurs. In this case, the robot is restarted at
the 'main' function, with the stack reset to all zeros.
For more information, see the section on machine instructions
and theory.
_7_. _C_R_o_b_o_t_s _C _c_o_m_p_i_l_e_r
_7_-_1_. _D_e_s_c_r_i_p_t_i_o_n
The CRobots compiler accepts a limited subset of the C
language. There is no provision for separate compilation, i.e.,
all modules of a program must be in one file. No preprocessor is
provided for "#define", "#include", etc. Identifiers are
significant to 7 characters, although any length may be used. The
Page 8
Tom Poindexter '85 David Wright '89-90
compiler will compile any file, but will convert any existing
extension to (or add the extension) ".cr". CRobots reserves the
extension ".cr" for "Compiled Robot", and will not like other files
using the same names. For consistency, use the extension ".r" for
robot source code files, and let the compiler convert them to
".cr".
_7_-_2_. _F_e_a_t_u_r_e_s _m_i_s_s_i_n_g _f_r_o_m _s_t_a_n_d_a_r_d _C
Major language features missing from K&R are: floating point
variables, structures, unions, pointers, initializers, arrays,
character data, typedefs, for statement, do..while statement,
switch..case statement, break, continue, gotos and labels, ternary
and comma operators, octal and hexadecimal constants, no parameters
to main(), no I/O functions, and all preprocessor directives.
_7_-_3_. _C_R_o_b_o_t_s _l_a_n_g_u_a_g_e
The language features that are present are entirely suitable for
writing robot control programs. Basic programming constructs of
if..then..else, while, and function calls can be used freely. Full
expression evaluation is also provided, so that statements such as:
if ((x = func1(y,1,++z,func2(c))) > 0)
a = 0;
else
a = x;
are perfectly legal. Ifs and whiles may be nested, and recursion is
supported. Variables declared outside a function definition are
global in scope, whereas variables declared inside a function
definition are local to that function.
The following keywords are recognized:
ccoommmmeennttss::
"/* ... */" comments cannot be nested
ccoonnssttaannttss::
any decimal digits, optionally preceeded with a '-'
ddeeccllaarraattiioonnss::
"int" variable declare
"long" same as int
"auto" default storage scope, optional
"register" legal, but ignored, same as auto
"function (parms,.....)" function definition
Page 9
Tom Poindexter '85 David Wright '89-90
llooggiicc ccoonnttrrooll::
"if (expr) STMT else STMT"
iitteerraattiioonn::
"while (expr) STMT"
ffuunnccttiioonn rreettuurrnn::
"return" return
"return expr" return with a value
aassssiiggnnmmeenntt ooppeerraattoorrss::
"=" assignment
">>=" assignment shift right
"<<=" assignment shift left
"+=" assignment addition
"-=" assignment subtraction
"*=" assignment multiplication
"/=" assignment division
"%=" assignment modulo
"&=" assignment and
"^=" assignment exclusive or
"|=" assignment inclusive or
bbiitt--wwiissee ooppeerraattoorrss::
">>" shift right
"<<" shift left
"&" and
"!" unary not
"~" unary one's complement
"^" exclusive or
"|" inclusive or
iinnccrreemmeenntt//ddeeccrreemmeenntt ooppeerraattoorrss::
"++" prefix or postfix increment
"--" prefix or postfix decrement
llooggiiccaall ooppeerraattoorrss::
"&&" logical and
"||" logical or
"<=" logical less than or equal
">=" logical greater than or equal
"==" logical equal
"!=" logical not equal
"<" logical less than
">" logical greater than
Page 10
Tom Poindexter '85 David Wright '89-90
aarriitthhmmeettiicc ooppeerraattoorrss::
"-" subtraction or unary negation
"+" addition
"*" multiplication
"/" division
"%" modulo
mmiisscc::
";" statement terminator or null statement
"{ }" compound statement
"," parameter separator in function definition or call
"( )" expression or function definition or call
Precedence and order of evaluation are the same as in K&R.
Operator Associativity
() left to right
! ~ ++ -- - right to left
* / % left to right
+ - " " "
<< >> " " "
< <= => > " " "
== != " " "
& " " "
^ " " "
| " " "
&& " " "
|| " " "
= -= += etc. right to left
Major derivations from K&R:
-Local variables need not be declared before reference, i.e., any
undeclared variable will default to a local variable.
-Intrinsic function names are reserved.
_7_-_4_. _C_o_m_p_i_l_e_r _l_i_m_i_t_s
defined functions: 64
local variables per function: 64
external variables: 64
if nest level: 16
while nest level: 16
line length 2000 bytes
Page 11
Tom Poindexter '85 David Wright '89-90
_7_-_5_. _C_o_m_p_l_i_e_r _e_r_r_o_r _a_n_d _w_a_r_n_i_n_g _m_e_s_s_a_g_e_s_:
The compiler has no error recovery and will stop on the first
error found. Warning messages do not stop the compiler.
EErrrroorr mmeessssaaggeess
"syntax error" - Any input that results in improper C syntax will
yield "syntax error", with an indicator pointing to the
unrecognizable input.
"instruction space exceeded" - compiler tried to generate more than
1000 machine instructions.
"symbol pool exceeded" - the maximum local variable, external
variable, or function definition symbol table was exceeded.
"function referenced but not found" - a function was referenced
that was not defined in the input file or is not an intrinsic
function.
"main not defined" - the input file did not define a 'main()'
function.
"function definition same as intrinsic" - a function was defined
with the same name as an intrinsic function, which is
reserved.
"if nest level exceeded" - more than 16 'if's were nested.
"while nest level exceeded" - more than 16 'while's were nested.
"yacc stack overflow" - the compiler's parser overflowed, probably
due to complex expressions and/or extreme nesting.
WWaarrnniinngg mmeessssaaggeess
These messages will not cause the compiler to fail, but may
cause the program to execute unexpectedly.
"unsupported initializer" - variable declares cannot include an
initializer. For future releases.
"unsupported break" - the 'break' statement was found and ignored.
For future releases.
"n undeclared variables" - one or more variables were implicitly
declared.
"code utilization: n%" - reports the capacity of machine
instructions generated.
Page 12
Tom Poindexter '85 David Wright '89-90
_7_-_6_. _C_o_m_p_i_l_e_r _N_o_t_e_s_:
The version 2.3 compiler will generate the postfix increment /
decrement operators, but you should be aware of the size penalty
when using them. Prefix operators only generate 3 instructions,
while postfix operations generate 5 instructions.
_8_. _C_R_o_b_o_t_s _C _I_n_t_r_i_n_s_i_c _F_u_n_c_t_i_o_n _L_i_b_r_a_r_y
The intrinsic function library provides machine level control
and certain arithmetic functions. These functions do not consume
any of the program code space or data stack, except for the three
words for call/return sequences. No explicit linking is required to
use any intrinsic function.
scan (degree,resolution)
The scan() function invokes the robot's scanner, at a specified
degree and resolution. scan() returns 0 if no robots are within the
scan range or a positive integer representing the range to the
closest robot. Degree should be within the range 0-359, otherwise
degree is forced into 0-359 by a modulo 360 operation, and made
positive if necessary. Resolution controls the scanner's sensing
resolution, up to +/- 10 degrees. Examples:
range = scan(45,0); /* scan 45, with no variance */
range = scan(365,10); /* scans the range from 355 to 15 */
cannon (degree,range)
The cannon() function fires the PPC at a specified range and
direction. cannon() returns 1 (true) if a pulse was discharged, or
0 (false) if the PPC is recharging. Degree is forced into the range
0-359 as in scan(). Range can be 0-700, with greater ranges
truncated to 700. Examples:
degree = 45; /* set a direction to test */
if ((range=scan(degree,2)) > 0) /* see if a target is there */
cannon(degree,range); /* fire a missile */
drive (degree,speed)
The drive() function activates the robot's drive mechanism, on a
specified heading and speed. Degree is forced into the range 0-359
as in scan(). Speed is expressed as a percent, with 100 as maximum.
A speed of 0 disengages the drive. Changes in direction can be
negotiated at speeds of less than 50 percent. Examples:
drive(0,100); /* head due east, at maximum speed */
drive(90,0); /* stop motion */
Page 13
Tom Poindexter '85 David Wright '89-90
damage()
The damage() function returns the current amount of damage
incurred. damage() takes no arguments, and returns the percent of
damage, 0-99. (100 percent damage means the robot is completely
disabled, thus no longer running!) Examples:
d = damage(); /* save current state */
; ; ; /* other instructions */
if (d != damage()) /* compare current state to prior state */
{
drive(90,100); /* robot has been hit, start moving */
d = damage(); /* get current damage again */
}
speed ()
The speed() function returns the current speed of the robot.
speed() takes no arguments, and returns the percent of speed,
0-100. Note that speed() may not always be the same as the last
drive(), because of acceleration and deacceleration delays.
Examples:
drive(270,100); /* start drive, due south */
; ; ; /* other instructions */
if (speed() == 0) /* check current speed */
{
drive(90,20); /* ran into the south wall, or another robot*/
}
loc_x () loc_y ()
The loc_x() function returns the robot's current x axis
location. loc_x() takes no arguments, and returns 0-999. The
loc_y() function is similar to loc_x(), but returns the current y
axis position.
Examples:
drive (180,50); /* start heading for west wall */
while (loc_x() > 20)
; /* do nothing until we are close */
drive (180,0); /* stop drive */
rand (limit)
The rand() function returns a random number between 0 and limit,
up to 32767.
Examples:
degree = rand(360); /* pick a random starting point */
range = scan(degree,0); /* and scan */
Page 14
Tom Poindexter '85 David Wright '89-90
sqrt (number)
The sqrt() returns the square root of a number. Number is made
positive, if necessary.
Examples:
x = x1 - x2; /* compute the classical distance formula */
y = y1 - y2; /* between two points (x1,y1) (x2,y2) */
distance = sqrt((x*x) - (y*y));
sin (degree) cos (degree) tan (degree) atan (ratio)
These functions provide trigonometric values. sin(), cos(), and
tan(), take a degree argument, 0-359, and returns the trigonometric
value times 100,000. The scaling is necessary since the robot cpu
is an integer only machine, and trig values are between 0.0 and
1.0. atan() takes a ratio argument that has been scaled up by
100,000, and returns a degree value, between -90 and +90. The
resulting calculation should not be scaled to the actual value
until the final operation, as not to lose accuracy. See
programming examples for usage.
_9_. _C_R_o_b_o_t_s _C _P_r_o_g_r_a_m _S_t_r_u_c_t_u_r_e
_9_-_1_. _B_a_s_i_c _p_r_o_g_r_a_m _s_t_r_u_c_t_u_r_e
CRobots programs are not unlike other C programs. The minimum
CRobots program consist of a function named "main". Additionally,
other functions can be defined, along with external variables.
There is one restriction about robot source files. The first 2
lines are reserved for the "Company" which produces a robot, and
the "Author" of the robot, respectively. As an example, a club may
use the same "company" name, while putting the programmer for each
robot in the "author" spot. This lets you share your robot with
other players, and still get credit for writing it. Both "company"
and "author" may be up to 15 characters long. If you do not want
these fields, you _M_U_S_T make the first 2 lines blank.
When a .r file is compiled, a file with the extension of .cr
will be created. This is the robot in a compiled and encrypted
format. You can give this file out for competition (as mentioned
above) without giving out your source code. Additionally, each .cr
file keeps track of wins and losses since the robot was last
compiled (needless to say, but to prevent major lawsuits,
recompiling a robot will clear out the stats).
Page 15
Tom Poindexter '85 David Wright '89-90
_9_-_2 _"_s_n_i_p_e_r_._r_"
The following CRobots program is provided as an example.
CRobots, Inc.
T. Poindexter
/* sniper */
/* strategy: since a scan of the entire battlefield can be done in 90 */
/* degrees from a corner, sniper can scan the field quickly. */
/* external variables, that can be used by any function */
int corner; /* current corner 0, 1, 2, or 2 */
int c1x, c1y; /* corner 1 x and y */
int c2x, c2y; /* " 2 " " " */
int c3x, c3y; /* " 3 " " " */
int c4x, c4y; /* " 4 " " " */
int s1, s2, s3, s4; /* starting scan position for corner 1 - 4 */
int sc; /* current scan start */
int d; /* last damage check */
/* main */
main()
{
int closest; /* check for targets in range */
int range; /* range to target */
int dir; /* scan direction */
/* initialize the corner info */
/* x and y location of a corner, and starting scan degree */
c1x = 10; c1y = 10; s1 = 0;
c2x = 10; c2y = 990; s2 = 270;
c3x = 990; c3y = 990; s3 = 180;
c4x = 990; c4y = 10; s4 = 90;
closest = 9999;
new_corner(); /* start at a random corner */
d = damage(); /* get current damage */
dir = sc; /* starting scan direction */
while (1) { /* loop is executed forever */
Page 16
Tom Poindexter '85 David Wright '89-90
while (dir < sc + 90) { /* scan through 90 degree range */
range = scan(dir,1); /* look at a direction */
if (range <= 700 && range > 0) {
while (range > 0) { /* keep firing while in range */
closest = range; /* set closest flag */
cannon(dir,range); /* fire! */
range = scan(dir,1); /* check target again */
if (d + 15 > damage()) /* sustained several hits, */
range = 0; /* goto new corner */
}
dir -= 10; /* back up scan, in case */
}
dir += 2; /* increment scan */
if (d != damage()) { /* check for damage incurred */
new_corner(); /* we're hit, move now */
d = damage();
dir = sc;
}
}
if (closest == 9999) { /* check for any targets in range */
new_corner(); /* nothing, move to new corner */
d = damage();
dir = sc;
} else /* targets in range, resume */
dir = sc;
closest = 9999;
}
} /* end of main */
/* new corner function to move to a different corner */
new_corner() {
int x, y;
int angle;
int new;
Page 17
Tom Poindexter '85 David Wright '89-90
new = rand(4); /* pick a random corner */
if (new == corner) /* but make it different than the */
corner = (new + 1) % 4;/* current corner */
else
corner = new;
if (corner == 0) { /* set new x,y and scan start */
x = c1x;
y = c1y;
sc = s1;
}
if (corner == 1) {
x = c2x;
y = c2y;
sc = s2;
}
if (corner == 2) {
x = c3x;
y = c3y;
sc = s3;
}
if (corner == 3) {
x = c4x;
y = c4y;
sc = s4;
}
/* find the heading we need to get to the desired corner */
angle = plot_course(x,y);
/* start drive train, full speed */
drive(angle,100);
/* keep traveling until we are within 100 meters */
/* speed is checked in case we run into wall, other robot */
/* not terribly great, since were are doing nothing while moving */
while (distance(loc_x(),loc_y(),x,y) > 100 && speed() > 0)
;
/* cut speed, and creep the rest of the way */
drive(angle,20);
while (distance(loc_x(),loc_y(),x,y) > 10 && speed() > 0)
;
/* stop drive, should coast in the rest of the way */
drive(angle,0);
} /* end of new_corner */
Page 18
Tom Poindexter '85 David Wright '89-90
/* classical pythagorean distance formula */
distance(x1,y1,x2,y2)
int x1;
int y1;
int x2;
int y2;
{
int x, y;
x = x1 - x2;
y = y1 - y2;
d = sqrt((x*x) + (y*y));
return(d);
}
/* plot course function, return degree heading to */
/* reach destination x, y; uses atan() trig function */
plot_course(xx,yy)
int xx, yy;
{
int d;
int x,y;
int scale;
int curx, cury;
scale = 100000; /* scale for trig functions */
curx = loc_x(); /* get current location */
cury = loc_y();
x = curx - xx;
y = cury - yy;
/* atan only returns -90 to +90, so figure out how to use */
/* the atan() value */
if (x == 0) { /* x is zero, we either move due north or south */
if (yy > cury)
d = 90; /* north */
else
d = 270; /* south */
} else {
if (yy < cury) {
if (xx > curx)
d = 360 + atan((scale * y) / x); /* south-east, quadrant 4 */
else
d = 180 + atan((scale * y) / x); /* south-west, quadrant 3 */
} else {
if (xx > curx)
d = atan((scale * y) / x); /* north-east, quadrant 1 */
else
d = 180 + atan((scale * y) / x); /* north-west, quadrant 2 */
}
}
Page 19
Tom Poindexter '85 David Wright '89-90
return (d);
}
Notes: The distance() and plot_course() routines are quite
handy. Save them for your programs. Also, note that the main scan
routine will "back up" a few degrees after a target has been found
and fired upon. This should catch robots trying to flee away from
the direction you are scanning. If the target moves the other way,
the normal scan increment will find it.
See the other sample CRobots program files.
_1_0_. _C_R_o_b_o_t_s _C_P_U _A_r_c_h_i_t_e_c_t_u_r_e _a_n_d _T_h_e_o_r_y
This information is provided if you need to use the debug
facility, or are curious about the virtual machine interpreter.
Don't bother reading this section if you are not so inclined; it is
not needed for normal play.
_1_0_-_1_. _S_t_a_c_k _u_s_a_g_e_:
The stack is controlled implicitly by several pointers. Stack
pointers are not accessible through machine instructions. Most
instructions will either push data onto the stack, or pop data off
the stack. The stack is used from the bottom up (low memory) for
data and temporary storage, and is used from the top down (high
memory) for saving stack pointers and the program counter on
function call/return.
External (global) variables are allocated at the very bottom of
the stack, and the local mark pointer for 'main' starts just after
the externals. External variables are addressed from the beginning
of the stack, by offset.
When a function is called (including 'main'), the stack pointer
is marked (local mark) and is increased by the number of local
variables needed for that function. Local variables are addressed
relative to the local mark, by offsets. All calculations, function
calls, and constants are pushed on and popped off the stack as
needed (temporary mark or top of stack).
A function call also saves its current stack pointers (local
variable mark and frame mark) and program counter. This return
information grows from the top down.
Arguments are passed to functions by value. The first argument
in a function call becomes the first local variable for the called
function. Consider the following:
main() /* main has three local variables: */
Page 20
Tom Poindexter '85 David Wright '89-90
{
int a, b, c;
....;
sub1 (a,b/2,c+1); /* call sub1, and pass arguments */
....;
}
sub1 (x,y,z) /* sub1 takes three parameters and */
int x, y, z; /* has one local variable */
{
int result;
result = x + y + z;
return (result);
}
The main() function allocates three local variables on the
stack, sets its local mark at 'a', and sets the temporary stack
pointer beyond the locals. Just before sub1() is called, the value
of 'a' is pushed, followed by the result of 'b/2', and 'c+1'. When
sub1() is called, it sets its local mark where the value of 'a' is,
so that 'a' is known as 'x' in func1(), likewise 'b/2' is known as
'y' and 'c+1' is known as 'z'. Sub1() also allocates one more word
for 'result', and sets the temporary mark after the storage for
'result'.
Page 21
Tom Poindexter '85 David Wright '89-90
The following diagram illustrates the stack usage:
+------------+ <-- end of stack, high memory
|main return | <-- return info for main
+------------+ (frame,ip,local mark)
|sub1 return | <-- return info for sub1
+------------+ (etc.)
| | |
| v | <-- additional function call return
| | info grow downwards
| |
| |
| |
| ^ | <-- additional function calls and
| | | expressions grow upwards
|expressions |
+------------+ <-- temporary mark (top of stack)
|sub1 locals |
+------------+ <-- local mark: sub1 function
|main locals |
+------------+ <-- local mark: main function
| |
| Externals |
| |
+------------+ <-- beginning of stack
_1_0_-_2_. _L_i_n_k _l_i_s_t
The link list is a list built by the compiler that contains the
names and link information of the functions within the program. The
link information contains the starting location of the function
within the code, the number of parameters, and the number of other
local variables within the function. The link list cannot be
accessed by the user program.
_1_0_-_3_. _I_n_s_t_r_u_c_t_i_o_n _s_e_t
The CRobots cpu has 10 instructions. Each instruction occupies
the same amount of storage, with or without operands.
FETCH offset (external | local) - Fetch will retrieve a word from
either the external variable pool or the local variable pool
and push it onto the stack. The offset has its high-bit set
(or'ed with 0x8000) if it is an external (offset from the
beginning of the stack), otherwise it is a local (offset from
the local variable mark). See STORE.
STORE offset (external | local), opcode - Store pops the top two
items, applies the arithmetic opcode to the two operands,
pushes the result on the top of the stack and stores it in the
variable referenced by the offset. Offsets are either external
Page 22
Tom Poindexter '85 David Wright '89-90
or local, according to the method described in Fetch. The
result of the opcode is left on the stack. See FETCH and
BINOP.
CONST k - Const will push a constant onto the stack.
BINOP opcode - Binop will pop the top two items as top of stack =
y, next to top of stack as x, apply the arithmetic opcode as
(x opcode y), and push the result on the stack. Opcodes are
decimal representations of 'C' operators such as '+', '/',
'>=', etc. See STORE.
FCALL link-offset - Fcall performs a high level function call
facility. The link-offset operand specifies an entry in the
link list table. Fcall pushes its return information: the
next instruction counter and the current local variable mark.
A new local variable mark and temporary mark (top of stack
pointer) is set. The cpu then branches to the first
instruction of the function. See RETSUB and FRAME.
RETSUB - Retsub returns from a function, leaving the return value
on the top of the stack. Retsub restores the previous local
variable pool, the next instruction counter, and re-adjusts
the stack frame to the point just before the call. The C
compiler generates code to return a dummy value if the
function does not explicitly return one. See FCALL and FRAME.
BRANCH instruction - Branch pops the top of the stack and branches
to the instruction if the value is zero. The next sequential
instruction is executed if the value is anything other than
zero.
CHOP - Chop discards the top of the stack by popping it into
oblivion.
FRAME - Frame facilitates fcall/retsub by saving the current top of
stack pointer (temporary mark) in anticipation of a fcall
statement. The top of stack pointer is saved in the
call/return stack as a frame marker. See FCALL and RETSUB.
NOP - No operation. Is used as a mark indicating the end of code.
_1_0_-_4_. _M_a_c_h_i_n_e _l_e_v_e_l _d_e_b_u_g_g_i_n_g
Debug mode is used to trace by single stepping machine
instructions. Use this only if you need to see your program
execute, or are just curious.
First, get a listing on paper of a compile with full information
by using the 'COMPILE TO' option:
A>crobots COMPILE TO prt: yourpgm.r
Page 23
Tom Poindexter '85 David Wright '89-90
Next, start CRobots again with the 'DEBUG' flag:
A>crobots DEBUG yourpgm.r
Your robot will be placed randomly in the field, and a target
robot will be placed at the center of the field (x=500,y=500) so
your robot program can find and shoot at a target.
The virtual machine interpreter will single step through your
program (machine instructions, that is). At every instruction, a
machine instruction is disassembled, and the top of stack pointer
and value are printed. The top of stack and value are after the
results of the instruction. Other information may also be printed,
such as function calls searching the link list, etc.
On every step, you are prompted "d,h,q,<cr>:". Entering 'd' will
dump external and local variable pools, as well as vital
information of your robot: coordinates, heading, speed, damage,
etc., and the status of any missiles your robot may have fired.
Entering 'h' will simulate your robot taking a 10% damage hit, so
you can check damage detection, etc. Entering 'q' will quit the
program immediately, and return you to AmigaDOS. A carriage return
alone will continue the stepping process. All responses ('d','h',
or 'q') should be in lower case only. You should refer to the
compile listing for offsets into the external and local variable
pools, C code, etc.
_1_1_. _I_m_p_l_e_m_e_n_t_a_t_i_o_n _n_o_t_e_s
CRobots is written entirely in 'C'. The compiler section was
developed with the aid of the Unix* (TM) programs 'yacc' and 'lex'.
Yacc (yet another compiler-compiler) accepts a 'grammar', which
describes the CRobots 'C' language. Yacc produces a 'C' function
known as a parser. The parser is the heart of the compiler,
recognizing valid 'C' constructs. Lex (lexical analyzer) accepts a
list of token combinations, and produces a 'C' function to scan the
compiler input for the tokens. The yacc generated parser,
yyparse(), repeatedly calls the lex generated analyzer, yylex(), to
process the source program. The initial screen display routines
were developed with the 'curses' screen library.
The 'C' source code was then ported to MS-DOS** (TM), and
recompiled using the Lattice*** (TM) 2.15E compiler, using the
'small' memory model. The screen display functions were modified to
use 'int86()', accessing the rom INT 10H cursor positioning
functions in the IBM-PC bios.
After it was ported to MS-DOS it was effectively abandoned by
Tom Poindexter, and at this time all attempts to contact him have
failed. I (David Wright) got a copy of it which had been ported to
the Amiga almost 2 years ago, and have been tracking down the
source code ever since. In September of 1989 I was finally able to
get the source (for the IBM/Unix version) and re-port it to the
Page 24
Tom Poindexter '85 David Wright '89-90
Amiga. At my first release it was still text based, but supported
the ARP command line handler, stack handler, and file requesters.
My next release included robots, explosions, and pulses as BOBs,
and 2 custom graphics screens. I also added the ability to
pre-compile the robots, so that they may be given out without the
source code for competition, and so that a win/loss ratio can be
encoded into the file. I also want to create a standalone robot
factory and test bench.
Tom was asking for money to get the source code, but I am not
going to be that strict. If you want the latest version of the
source, send me a self-addressed, stamped envelope with a single
floppy also included. I will copy that latest, released, version I
have onto it, and throw in my latest version of CoreWar to boot.
* Unix is a trademark of Bell Telephone Laboratories.
** MS-DOS is a trademark of Microsoft, Inc.
*** Lattice is a trademark of Lattice, Inc.
**** IBM is a trademark of International Business Machines, Inc.
Page 25
Table of Contents
1. Distribution Agreement.................................. 1
2. Introduction............................................ 1
2-1. Description........................................ 1
2-2. Intended Audience.................................. 1
2-3. Machine requirements............................... 1
2-4. User Interface..................................... 2
3. Types of Play........................................... 2
4. Running CRobots......................................... 2
4-1. Command Line Options............................... 2
4-2. Examples........................................... 3
4-3. Running CRobots from the WorkBench................. 4
4-4. Workbench examples................................. 4
5. Game Parameters......................................... 4
5-1. Battlefield........................................ 4
5-2. Robot Offense...................................... 5
5-3. Robot Defense...................................... 5
5-4. Disabling Opponents................................ 6
5-5. Sample Display..................................... 7
5-6. Table of Time Costs................................ 7
6. CRobots CPU............................................. 8
7. CRobots C Compiler...................................... 8
7-1. Description........................................ 8
7-2. Features Missing From Standard C................... 9
7-3. CRobots Language................................... 9
7-4. Compiler Limits.................................... 11
7-5. Compiler Error & Warning Messages.................. 11
7-6. Compiler Notes:.................................... 12
8. CRobots Intrinsic Function Library...................... 13
9. CRobots C Program Structure............................. 15
9-1. Basic Program Structure............................ 15
9-2. "sniper.r"......................................... 15
10. CRobots CPU Architecture and Theory.................... 20
10-1. Stack usage....................................... 20
10-2. Link list......................................... 22
10-3. Instruction set................................... 22
10-4. Machine level debugging........................... 23
11. Implementation notes................................... 24
- I -